package com.ruoyi.project.app.util;

import com.ruoyi.common.utils.StringUtils;

import java.security.MessageDigest;
import java.text.SimpleDateFormat;
import java.util.*;

/**
 * token工具类
 */
public class TokenUtil {
    private static final TokenUtil instance = new TokenUtil();
    private final int INTERVAL = 7 * 24 * 60 * 60 * 1000;// token过期时间间隔天
    private final String NAMESPACE = "testMRf1$789787aadfjkds//*-+'[]jfeu;384785*^*&%^%$%.token";// 命名空间
    private Map<String, Object> srcData = new HashMap<>();

    public static TokenUtil get() {
        return instance;
    }

    /**
     * 清空数据
     *
     * @return TokenUtil
     */
    public TokenUtil clear() {
        if (srcData == null) srcData = new HashMap<>();
        if (srcData.size() > 0) srcData.clear();
        return this;
    }

    /**
     * 添加数据
     *
     * @param key   键
     * @param value 值
     * @return TokenUtil
     */
    public TokenUtil put(String key, String value) {
        if (!StringUtils.isEmpty(key) && !StringUtils.isEmpty(value)) {
            srcData.put(key, value);
        }
        return this;
    }

    /**
     * 创建token
     *
     * @return 返回token
     */
    public String createToken() {
        //添加命名空间
        srcData.put("namespace", NAMESPACE);
        //添加时间戳
        srcData.put("time", new Date().getTime());
        return authentication(srcData);
    }

    /**
     * 验证token
     *
     * @param tokenSrc 原始的token
     * @param token    要验证的token
     * @return true 表示验证通过
     */
    public boolean validToken(String tokenSrc, String token) {
        if (StringUtils.equals(tokenSrc, token)) {
            return true;
        }
        return false;
    }

    /**
     * 身份验证token值算法：
     *
     * @param data 约定用来计算token的参数
     * @return 生成的token
     * 算法是：将特定的某几个参数一map的数据结构传入，
     * 进行字典序排序以后进行md5加密,32位小写加密；
     */
    private String authentication(Map<String, Object> data) {
        if (data != null) {
            //排序，根据keyde 字典序排序
            List<Map.Entry<String, Object>> list = new ArrayList<>(data.entrySet());
            Collections.sort(list, new Comparator<Map.Entry<String, Object>>() {
                //升序排序
                public int compare(Map.Entry<String, Object> o1, Map.Entry<String, Object> o2) {
                    return o1.getKey().compareTo(o2.getKey());
                }
            });

            //拼接字符串
            StringBuilder builder = new StringBuilder();
            for (Map.Entry<String, Object> srcAtom : list) {
                builder.append(String.valueOf(srcAtom.getValue()));
            }
            //计算token
            return encryptMD5(builder.toString());
        } else {
            return "";
        }
    }

    /**
     * md5加密算法
     *
     * @param str 要加密的字符串
     * @return 已加密的字符串
     */
    private String encryptMD5(String str) {
        try {
            MessageDigest md = MessageDigest.getInstance("MD5");
            md.update(str.getBytes());
            StringBuilder sb = new StringBuilder();
            byte[] bytes = md.digest();
            //将字节数组转换成16进制字符串
            for (byte bs : bytes) {
                int b = bs & 0xFF;
                if (b < 0x10) sb.append('0');
                sb.append(Integer.toHexString(b));
            }
            return sb.toString();
        } catch (Exception e) {
            return "";
        }
    }

    public static void main(String[] args) {
        String[] dur ="4/0/1".split("/");
        Calendar calendar = Calendar.getInstance();
        calendar.setTime(new Date());
        if(dur.length == 1){
            calendar.add(Calendar.MONTH, Integer.parseInt(dur[0]));
        }else if(dur.length == 3){
            System.out.println("year:"+Integer.parseInt(dur[0]));
            calendar.add(Calendar.YEAR, Integer.parseInt(dur[0]));
            if(Integer.parseInt(dur[1])>0){
                System.out.println("month:"+Integer.parseInt(dur[1]));
                calendar.add(Calendar.MONTH, Integer.parseInt(dur[1]));
            }
            if(Integer.parseInt(dur[2])>0){
                System.out.println("day:"+Integer.parseInt(dur[2]));
                calendar.add(Calendar.DATE, Integer.parseInt(dur[2]));
            }
        }
        SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
        System.out.println(sdf.format(calendar.getTime()));

    }
}
